<!DOCTYPE html>
<html>
<head>
    <title>Pulley System Physics Diagram</title>
</head>
<body>
<canvas id="canvas" width="400" height="560"></canvas>
<script>
    const canvas = document.getElementById('canvas');
    const ctx = canvas.getContext('2d');

    // --- Style and coordinate definitions ---
    const cx = canvas.width / 2; // 200
    const groundY = 500;
    const ropeSpacing = 100;
    const ropeAx = cx - ropeSpacing / 2; // 150
    const ropeBx = cx + ropeSpacing / 2; // 250
    const pulleyRadius = ropeSpacing / 2; // 50
    const pulleyCenterY = 200;

    // --- Create texture pattern ---
    // This pattern mimics the grainy/stippled texture in the original image.
    const patternCanvas = document.createElement('canvas');
    const pCtx = patternCanvas.getContext('2d');
    patternCanvas.width = 4;
    patternCanvas.height = 4;
    pCtx.fillStyle = '#E0E0E0'; // Base gray color for the pattern
    pCtx.fillRect(0, 0, 4, 4);
    pCtx.fillStyle = '#C0C0C0'; // Darker dots for texture
    pCtx.fillRect(0, 1, 1, 1);
    pCtx.fillRect(2, 3, 1, 1);
    const texturePattern = ctx.createPattern(patternCanvas, 'repeat');

    // --- Draw Ground ---
    ctx.beginPath();
    ctx.moveTo(cx - 160, groundY);
    ctx.lineTo(cx + 160, groundY);
    ctx.lineWidth = 2;
    ctx.strokeStyle = '#333';
    ctx.stroke();
    // Add some subtle texture to the ground
    ctx.lineWidth = 1;
    ctx.strokeStyle = '#999';
    for (let i = 0; i < 30; i++) {
        const x1 = cx - 160 + Math.random() * 320;
        const x2 = x1 + 5 + Math.random() * 10;
        const y = groundY + 2 + Math.random() * 4;
        ctx.beginPath();
        ctx.moveTo(x1, y);
        ctx.lineTo(x2, y);
        ctx.stroke();
    }
    
    // --- Draw Block A ---
    const blockA = { w: 80, h: 100 };
    blockA.x = ropeAx - blockA.w / 2;
    blockA.y = groundY - blockA.h;
    ctx.beginPath();
    ctx.rect(blockA.x, blockA.y, blockA.w, blockA.h);
    ctx.fillStyle = texturePattern;
    ctx.fill();
    ctx.lineWidth = 2;
    ctx.strokeStyle = 'black';
    ctx.stroke();
    ctx.fillStyle = 'black';
    ctx.font = 'bold 28px sans-serif';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    ctx.fillText('A', ropeAx, groundY - blockA.h / 2);

    // --- Draw Block B ---
    const blockB = { w: 70, h: 50 };
    blockB.x = ropeBx - blockB.w / 2;
    blockB.y = groundY - blockB.h;
    ctx.beginPath();
    ctx.rect(blockB.x, blockB.y, blockB.w, blockB.h);
    ctx.fillStyle = texturePattern;
    ctx.fill();
    ctx.stroke();
    ctx.fillStyle = 'black';
    ctx.fillText('B', ropeBx, groundY - blockB.h / 2);

    // --- Draw Pulley System ---
    // Ropes
    ctx.lineWidth = 1.5;
    ctx.beginPath();
    // Rope A
    ctx.moveTo(ropeAx, blockA.y);
    ctx.lineTo(ropeAx, pulleyCenterY);
    // Arc over pulley
    ctx.arc(cx, pulleyCenterY, pulleyRadius, Math.PI, 0);
    // Rope B
    ctx.lineTo(ropeBx, blockB.y);
    ctx.stroke();

    // Pulley Wheel
    ctx.beginPath();
    ctx.arc(cx, pulleyCenterY, pulleyRadius, 0, 2 * Math.PI);
    ctx.fillStyle = '#808080'; // Darker solid gray as in the image
    ctx.fill();
    ctx.lineWidth = 2;
    ctx.stroke();

    // Pulley Bracket
    const bracketW = 20;
    const bracketH = 60; // Height from axle upwards
    const bracketY = pulleyCenterY - bracketH;
    ctx.beginPath();
    ctx.rect(cx - bracketW / 2, bracketY, bracketW, bracketH);
    ctx.fillStyle = texturePattern; // Bracket has same texture as blocks
    ctx.fill();
    ctx.stroke();

    // --- Draw Force F ---
    const forceLineTopY = 80;
    const forceArrowTipY = 60;
    ctx.lineWidth = 2;
    ctx.beginPath();
    ctx.moveTo(cx, bracketY);
    ctx.lineTo(cx, forceArrowTipY);
    ctx.stroke();
    // Arrowhead
    const arrowSize = 10;
    ctx.beginPath();
    ctx.moveTo(cx, forceArrowTipY);
    ctx.lineTo(cx - arrowSize / 2, forceArrowTipY + arrowSize);
    ctx.moveTo(cx, forceArrowTipY);
    ctx.lineTo(cx + arrowSize / 2, forceArrowTipY + arrowSize);
    ctx.stroke();

    // Force Label 'F'
    ctx.font = 'italic bold 26px serif';
    ctx.fillText('F', cx + 20, forceArrowTipY + 8);

    // --- Draw Bottom Text ---
    ctx.font = '24px "SimSun", "Microsoft YaHei"';
    ctx.fillStyle = '#333';
    ctx.fillText('习题 1-29 图', cx, 540);

</script>
</body>
</html>